Copyright (c) 1999 Massachusetts Institute of Technology

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, see https://gnu.org/licenses or write
to:
  Free Software Foundation, Inc.
  51 Franklin Street, Fifth Floor
  Boston, MA 02110-1301
  USA
------------------------------

PROGRAMMING TECHNOLOGY DIVISION DOCUMENT                     SYS.xx.yy


IDENTIFICATION�______________

     The JOB/BOJ Device:  A Mechanism for Implementing
                          Non-standard Devices

     Marc S. Seriff, Jack Haverty, Richard Stallman (MIT-AI)

     September 18, 1974


INTRODUCTION�____________

     It is occasionally desirable to extend the ITS system to allow

for the use of non-standard I/O devices.  A very desirable feature

would be to allow user-level programs to make use of the newly defined

devices with out modification of the user-level programs.  For this

reason the JOB/BOJ device was implemented.

     When a job (call it the user) attempts an OPEN for a file whose

name is "JOB: <-dir>-; <-fn1>- <-fn2>-", the system creates a

new job, called the BOJ device handler, or BDH (this is a terrible

name; it USES the BOJ device and HANDLES the JOB device), and attempts

to load the file "DSK: <-dir>-; <-fn1>- <-fn2>-" into that job.

If the load fails, the OPEN will fail.  If this load succeeds, the

OPEN, as well as all further I/O operations on the user's JOB channel

will be referred to the BDH for execution.  At that point, it will be

up to the BDH to decide whether or not the open should fail.  In order

to get a handle on information about the user's open, The BDH opens

one or more channels to the "BOJ" device.  The system will insure that

the BDH's BOJ channel is logically linked to the user's JOB channel.

The following diagram illustrates what happens:
PTDD                                2                        SYS.xx.yy



        __________                    _________
       |          |                  |         |
       |   User   |------v__________------>|   BDH   |
       |__________| | | ---XO---  | | |_________|
                    | |  Sys|tem  | |
                ____| |_____|_____| |____
               |v           |            |v
        The JOB channel    |     The BOJ channel
                           |
                           |v
                     System mediates


     Once the BDH has successfully opened the BOJ channel, it will be

notified (via an I/O channel interrupt) every time the user attempts

an I/O operation on the JOB channel.  The BDH may then examine the

data that is made available to it about the I/O operation and may

simulate the operation for the user.  In this way, BDHs can be written

to give anything the appearance of a disk, tape or other specific type

of I/O device.

USING THE JOB DEVICE�_____ ___ ___ ______

     Programs that use the JOB device should not be required to make

special provisions.  A BDH should, in general, be written so that the

non-standard device will behave exactly like some standard device.  In

other words, a user program may open a JOB device using a standard

open and may then execute any legal I/O operation.

     A file name with something other than "JOB" for a device code can

be made to act like a JOB device in one of two ways.  The first way

should be used for devices that are not generally applicable or are

expected to be used only for a short time.  To use this method simply

use translates (using MONIT, DDT or directly via system calls) to

inform the system which file should be used as a BDH.  For instance,

if we translate all file names of the form "XXX:" into the file name
PTDD                                3                        SYS.xx.yy


"JOB:ABC;TS RUNXXX", then the system will use the file "DSK:ABC;TS

RUNXXX" as the BDH for any file name whose device code is "XXX".

     The other method is much simpler and is designed for non-standard

devices that are to be made available to the entire user community.

When an OPEN is attempted on a device whose name the system does not

recognize, the system will examine the "DEVICE;" directory for a file

whose first name is "JOBDEV" and whose second name is the unrecognized

device name.  If such a file exists, then the contents of that file

will be loaded by the system and used as the BDH for the user's OPEN.

USING THE BOJ DEVICE - THE BOJ DEVICE HANDLER�_____ ___ ___ ______ _ ___ ___ ______ _______

     The BDH is the workhorse in the JOB/BOJ device scheme.  It is

required to interpret all of the user's I/O operations.  It must do

everything to make the non-standard device that it represents appear

standard.  The system provides five .CALLs to give the BDH some of the

required communcation with the user.

     The first thing that the BDH should do when he is loaded and

started by the system is to execute an OPEN on the BOJ device.  This

establishs a logical link between the user and the BDH.  The BDH may

enable a channel interrupt on the BOJ channel, in order to be informed

whenever the user attempts an I/O operation.

     It should be noted that the ITS system allows for the possibility

of a full duplex connection between the user and the BDH (i.e. a

channel in each direction).  If a user attempts an open for reading

and an open for writing on the same device, then the system will

present both opens to the same activation of the BDH.  Should this be

undesirable for a particular BDH, that BDH should use an open mode

with the 3.4 bit set (10 in the left half) each time it attempts to

open the BOJ device.
PTDD                                4                        SYS.xx.yy


JOBCAL SYSTEM CALL�______ ______ ____

     The first .CALL that will be discussed is the JOBCAL.  This call

enables the BDH to find out what I/O operation the user has attempted

to execute.  It has the following calling sequence:

        .CALL   JOBCAL
        ...             ; Error return
        ...             ; Success return

JOBCAL: SETZ
        SIXBIT/JOBCAL/
        [<-BOJ channel number>-]
        2000,,<-opcode>-
        SETZ [-<-n>-,,<-data>-]


This .CALL, as well as the other three discussed below, will fail to

skip if any of the following conditions hold:

        1.  <-BOJ channel number>- is an illegal channel number.

        2.  <-BOJ channel number>- is not open on the BOJ device.

        3.  the user job does not exist or as has closed his channel.

        4.  the user job is no longer attempting to execute the I/O
            operation.

     <-opcode>- should be an address into which information about

the I/O operation requested will be placed.  This word contains three

sections.  The right half of the word contains an integer indicating

which operation was attempted.  The following table indicates what the

various integers mean:
PTDD                                5                        SYS.xx.yy



       CODE  OPERATION�       ____  _________

        0    OPEN

        1    IOT (transfer)

        2    STATUS (currently unused)

        3    RESET

        4    RCHST (complete status)

        5    ACCESS

        6    FDELE (for delete or rename while not open)

        7    FDELE (for rename while open)

        8    CALL (see below)

It is up to the BDH to insure that these I/O operations perform as

they would for standard ITS devices.

     The top three bits (4.9-4.7) of the op-code word contain the mode

in which user is attempting to open his channel.  This is only

meaningful for op-code 0, OPEN.  If either of the next two bits (4.6

and 4.5) are non-zero, then the user is requesting that a channel be

closed.  As was mentioned above, the system allows the connection

between user and BDH to be full dumplex.  If the 4.6 bit of the opcode

is set, then the user is requesting that his input channel be closed,

while the 4.5 bit requests a close of the user's output channel.  It

is possible to get an opcode in which both bits are set.  In the case

the BDH should perform the obvious task of closing both channels.

     Most I/O operations require more information than just the name

of the operation.  The third argument to JOBCAL tells the system where

any additional information that is available should be placed.

<-n>- is the largest number of words that the BDH is willing to
PTDD                                6                        SYS.xx.yy


accept (it should normally be 12).  <-data>- is the address where

the first word of the information should be placed.  What information

is placed in this buffer is determined by the I/O operation being

attempted.

     If the op-code (in the right half of the op-code word) is less

than 8, then five words will be written into the buffer (beginning at

<-data>-) in response to the JOBCAL.  The meanings of the words are

given in the following table:
PTDD                                7                        SYS.xx.yy



WORD          OPERATIONS               MEANING�____          __________               _______

  1      IOT (1)                  Meaningful only for block IOTs.
                                  This word will contain the user's
                                  IOT pointer.  The left half of this
                                  word will be the negative of the
                                  number of words that the user wants.

  1      ACCESS (5)               The address within the virtual file
                                  that is open from (or to) which the
                                  next IOT should be done.  The first
                                  word of the virtual file is word
                                  zero.

  1      FDELE (6 or 7)           Zero implies delete requested.
                                  Non-zero means that a rename is
                                  requested.  This word is the name
                                  (in sixbit) to be used as the new
                                  first file name.

  2      OPEN (0) or FDELE (6)    First name of the file that the user
                                  is attempting to open, rename or
                                  delete.

  3      OPEN (0) or FDELE (6)    Second name of the file that the
                                  user is attempting to open, rename
                                  or delete.

  4      OPEN (0) or FDELE (6)    Name of directory to be used for
                                  open, rename or delete.

  5      OPEN (0) or FDELE (6)    Name of device to be used for open,
                                  rename or delete.

  6      OPEN (0)                 The full 18 bit open mode (right
                                  justified).

  6      FDELE (6 or 7)           Zero implies delete.  Non-zero means
                                  that a rename is requested.  This
                                  word is the name (in sixbit) to be
                                  used as the new second file name.

     If the op-code returned by JOBCAL is 8, then the user has

attempted some I/O operation not recognized by the systems JOB/BOJ

device code (this does not mean that the operation is illegal).  In�                       ___

this case, more information is written into the BDH's buffer (up to

twelve words).  The first of the data words will be the SIXBIT name of
PTDD                                8                        SYS.xx.yy


the operation being performed.  (This will normally be the name of the

.CALL executed by the user - see Appendix 1 for a list of

possiblities.) The second word will contain all of the flags that the

user has set using the "flag" feature of the .CALL UUO.  The third

word will be an integer indicating how many input (to the system)

arguments the user supplied in his .CALL.  It should be noted that if

this integer is larger than <-n>-+3, then some information will be

lost.  The values of the input arguments will appear in the remainder

of the words in the buffer.  Remember that, in almost all cases, the

first of the input arguments will be the user's channel number.

JOBRET SYSTEM CALL�______ ______ ____

     Once the BDH has interpreted the user's request for execution of

an I/O operation, the BDH must have some way of responding to the

user.  This is provided with the JOBRET .CALL.  This .CALL serves

three purposes:

        1.  to unblock the user who is waiting for completion of his
            I/O request (possibly causing the request to skip)

        2.  to set lossage codes in the user's status words (e.g. for
            failed opens).

        3.  to return information requested by the user's I/O
            operation.

The format of this CALL is as follows:

        .CALL   JOBRET
        ...             ; error return
        ...             ; success return

JOBRET: SETZ
        SIXBIT /JOBRET/
        [<-BOJ channel number>-]
        [<-return>-]
        SETZ [-<-n>-,,<-data>-]


where <-return>- satisfies requirements 1 and 2 above.  If
PTDD                                9                        SYS.xx.yy


<-return>- is zero, then the user's I/O call will not skip or set

status bits.  If <-return>- is of the form <-i>-,,<-j>- , then

<-i>- will be placed in the "open-loss" field of the status word for

the user's channel and the user's I/O call will skip <-j>- times.  A

list of all currently recognized open loss codes can be found in

Appendix 2.

     If the user's I/O call requested data, then the BDH can supply

this data by supplying the third argument to the JOBRET call.  The

system will use the <-n>- words beginning at location <-data>- as

the values for the return arguments in the user's call.

SETIOC AND JOBINT -- INTERRUPT SYSTEM CALLS�______ ___ ______ __ _________ ______ _____

     There are two interrupt oriented functions that the BDH must

perform and there are CALLs available to perform them.  The first is

to notify the user when he has done something catastrophic.  The user

should be notified of his error by causing the system to awaken him

with an I/O channel error.  This done with the SETIOC call, as

follows:

        .CALL   SETIOC
        ...             ; error return (standard reasons
                                + illegal IOCERR code)
        ...             ; success return

SETIOC: SETZ
        SIXBIT/SETIOC/
        [<-BOJ channel number>-]
        SETZ [<-IOCERR code>-]


where <-IOCERR code>- is an integer identifying the reason for the

error.  This integer should be chosen from the list that can be found

in Appendix 2.  Since BDHs are written to handle non-standard devices,

these error codes will quite often not apply.  Simply choose the code

that comes closest.
PTDD                                10                       SYS.xx.yy


     Occassionally, the BDH must notify the user of a non-catastrophic

situation (e.g. the arrival of data).  The JOBINT call allows the BDH

to give the user a second-word I/O channel interrupt, as follows:

        .CALL   JOBINT
        ...             ; error return
        ...             ; success return

JOBINT: SETZ
        SIXBIT /JOBINT/
        SETZ [<-BOJ channel number>-]


JOBSTS SYSTEM CALL�______ ______ ____

     Finally, the BDH must have some way to notify the system what the

status of the pseudo-device is.  For this purpose, the JOBSTS call is

available.  Its calling sequence is as follows:

        .CALL   JOBSTS
        ...             ; error return
        ...             ; success return

JOBSTS: SETZ
        SIXBIT /JOBSTS/
        [<-BOJ channel number>-]
        SETZ [<-new status>-]


The right half of <-new status>- will be given to anyone requesting

the status of the user's channel until another JOBSTS is done.  It

should be remembered that the low order six bits (1.1-1.6) should

contain the device code of the pseudo-device.  Unless, you know what

you are doing, this should always be 22 octal.

DATA TRANSFERS - HOW TO IOT�____ _________ _ ___ __ ___

     Since the main purposes of I/O devices is transfer of

information, let us look at how the BDH manages to respond to the

user's IOTs.  The method for doing this is very simply.  If we think

back to the diagram presented early in this memo, we will remember
PTDD                                11                       SYS.xx.yy


that the BOJ and JOB channels (i.e. the channels belonging to the BDH

and the user, respectively) are logically connected.  The full meaning

of this now becomes clear.  If the JOB channel is open for input and

the BOJ channel is open for output, then anything that BDH outputs on

the BOJ channel will be available to the user as input on the JOB

channel.  (For this reason, the BDH must insure that he opens the BOJ�                                    ____

channel in the opposite direction from the user's JOB channel even if

this requires opening the BOJ channel a second time in the correct

mode.)

     There are two features of which the BDH implementer should be

aware when writing the I/O sections of the BDH.  Let us assume for the

discussion here, that the user has the JOB channel open for reading

and that the BDH has the BOJ channel open for writing.  Let us also

assume that the user is currently hung attempting to read 100 words on

his JOB channel.

     First it should be noted that the BDH does not have to respond to�                                                ___

this request with a single transfer of 100 words.  The system will act

as an mediator between different transfer sizes.  The BDH can respond

to the user's request for 100 words in several ways:

        1.  He can send all 100 words in small pieces (e.g. 10

            transfers of 10 words each.

        2.  He can send all 100 words in a single transfer.

        3.  He can send more than 100 words.  In this case, the BDH

            will remain hung in his IOT until the user has read all of

            the data that the BDH is attempting to send.  (If this is

            undesirable, set the 3.5 in the BOJ open mode.  This will

            cause BOJ IOTs to unhang whenever the user's IOT is
PTDD                                12                       SYS.xx.yy


            satisfied. When that happens, the BOJ IOT pointer will

            have been counted out only partially; the RH will point to

            the first word not transfered)

        4.  He may send less than 100 words.  In this case, the BDH

            must manually awaken the user as described below.

The user, who is hung awaiting his 100 words, will stay hung until he

has received all 100 words.  Suppose, however, that the BDH only

wishes to send 50 words (e.g. the last 50 words of the virtual file).

To do this, he can send the 50 words normally, but must then use the

JOBRET call (described above) to awaken the user.  JOBRET should be

called with the BOJ channel number as the first argument, zero as the

second argument and no third argument.  Secondly, the BDH implementer

must be aware that the ITS system guarantees that IOTs to a channel

open in block mode, will never generate an I/O channel error.  In

other words, the following algorithm should be followed:

        1.  If the user requests n words and there are n words or more

            left in the "file", give him n words.

        2.  If the user requests n words and there are only m words

            (n>m), give him m words and manually awaken him (using

            JOBRET).

        3.  If the user requests n words and there are no words left,

            then give him nothing and manually awaken him (using

            JOBRET).

HINTS TO BDH IMPLEMENTERS�_____ __ ___ ____________

     The following hints should ease the task of BDH implementers a

little.  It is hoped that anyone who attempts to a BDH implementation

will add his harshly acquired knowledge to this section of this memo.
PTDD                                13                       SYS.xx.yy


1.  Remember that the BDH is essentially a disowned job and should

    attempt to log out after a close has been requested.

2.  Be very leery of logging out for any reason other than a requested

    CLOSE.  In particular:

    a.  if a JOBCAL fails, only log out if a request for OPEN has not

        yet been received.

    b.  when you generate an I/O channel error for the user, only log

        out if the error is irrecoverable.  Remember that he can

        correct an access beyond end-of-file by doing an access before

        attempting another IOT.

    c.  if he requests an I/O operation that you do not recognize,

        generate a "mode not available" error (via JOBRET) and wait

        for his next request.

    d.  if you decide, for your own reasons, to make the initial open

        fail, you should log out.

THE OJB DEVICE -- AN AID FOR DEBUGGING THE BDH�___ ___ ______ __ __ ___ ___ _________ ___ ___

     One of the problems with debugging BDH programs is that when the

JOB device is used, it is loaded into a newly created job. That job is

not inferior to any DDT, and there is no way to put breakpoints in it

before it starts. The OJB device makes it possible to run the BDH

program under DDT.

     The OJB device acts just like the JOB device except during the

initial open. When the JOB device would be creating and loading a new

job, the OJB device is looking for an existing job whose UNAME and

JNAME are the same as the filenames specified in the open.  If such a

job is found, it is connected to the job opening the OJB device

through a standard JOB-BOJ pipeline.  If such a job does not exist,
PTDD                                14                       SYS.xx.yy


the open of the OJB device fails.  In order to protect innocent jobs

from being hacked in this matter, the job opened on the OJB device is

required to have set its OPTOJB bit (this is bit 4.2 in the .OPTION

varisble, settable with .SUSET).  Also, it must not already be a BDH,

for the system cannot consider one job to be a BDH through two

connections at once.  If either of those conditions is not met, the

OJB open WAITS until they are.

     To remove a possible timing screw, a BOJ device open by a job

that is not a BDH, which usually fails, will wait instead for the job

to become a BDH if the job's OPTOJB bit is set.

     The procedure for using the OJB device for debugging is:


     1.  create a job to use for the BDH (call it J, in this example).

     2.  run (in another job) the program which would normally open

the JOB device, but tell it (perhaps by means of a translation) to use

the OJB device instead.  This program's function is to issue system

calls so that the BDH's responses to them can be tested.

     Since the OPTOJB bit of job J is now 0, when this program reaches

the OJB open it will hang.

     3.  ^Z that program, and ^P it. it will go back to hanging in the

open of the OJB device.

     4.  switch to job J, load in the BDH program.  This RESET's the

job so that if it had been a BDH before, it will not be one now.

     5.  turn on the OPTOJB bit by depositing from DDT in .OPTION.

The conditions for a successful OJB open by job JJ have now been met,

so that job will make some headway, turning job J into a BDH and

waiting for job J to issue a JOBRET.
PTDD                                15                       SYS.xx.yy


     6.  it is now possible to start running job J, with breakpoints

as desired, to step through the code for handling the initial open.

It is unlikely, but theoretically possible, for J to execute its BOJ

open before JJ gets around to turning J into a BDH.  In this case, J

will wait for JJ to do so.

     7.  if it becomes necessary to try again after discovering a bug,

go back to step 2.  The OJB open will hang up this time not because

the OPTOJB bit is off (since it is still 1) but because J is already a

BDH.  Loading J in step 4 will make J cease to be a BDH but also turn

off the OPTOJB bit, so JJ will still be waiting.

     8.  it is possible for job JJ to be "PCLSR'ed" or backed up out

of its open while job J is being traced through the handling of the

initial open.  For example, job JJ might receive a real-time

interrupt.  If that happens, J will cease to be a BDH.  This will not

interfere with the tracing of J until the next BOJ device system call

is executed; that call will probably fail.  It is impossible to

continue after such an occurrence, so the jobs must be restarted by

returning to step 2.  Of course, if there are no breakpoints before

the first JOBRET, this is very unlikely to happen.

     9.  if the initial open has been handled successfully, to go on

to debug handling of other system calls, simply tell JJ to execute

them with J stopped while JJ is being told, then ^Z^P JJ and go back

to J.

     10. the usual .LOGOUT in the BDH program will be a no-op when the

program is run as an inferior in this manner, so it should be followed

by a .VALUE.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 